import { _decorator, Component, Node, Prefab, resources, sys, assetManager, AssetManager, Asset, director, __private } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('LoadCtrl')
export class LoadCtrl {

    static async loadPrefab(path: string, callback: Function = null) {
        let p = await new Promise((resolve, reject) => {
            resources.load(path, Prefab, (err, prefab) => {
                if (err) {
                    reject(err);
                    console.error('Failed to load prefab:', err);
                    return;
                }
                resolve(prefab);
            });
        });

        callback && callback(p);

        return p;
    }

    static async loadPrefabs(paths: Array<string>, callback: Function = null) {
        let ps = await new Promise((resolve, reject) => {
            resources.load(paths, Prefab, (err, prefabs) => {
                if (err) {
                    reject(err);
                    console.error('Failed to load prefabs:', err);
                    return;
                }
                resolve(prefabs);
            });
        });

        callback && callback(ps);

        return ps;
    }

    static async loadBaseAllRes<T extends Asset>(path: string, type: __private.__types_globals__Constructor<T>) {
        let ps = await new Promise<T[]>((resolve, reject) => {
            resources.loadDir(path, type, (err, prefabs) => {
                if (err) {
                    reject(err);
                    console.error('Failed to load prefabs:', err);
                    return;
                }
                resolve(prefabs);
            });
        });

        return ps;
    }

    static async loadBaseRes<T extends Asset>(path: string, type: __private.__types_globals__Constructor<T>): Promise<T> {
        let ps = await new Promise<T>((resolve, reject) => {
            resources.load(path, type, (err, res) => {
                if (err) {
                    reject(err);
                    console.error('Failed to load prefabs:', err);
                    return;
                }
                resolve(res as T);
            });
        });
        return ps;
    }

    /**
     * 加载bundle下某文件夹中的一种类所有资源
     * @param path 
     * @param type 
     * @param succeed 
     */
    static async loadBundleAllRes<T extends Asset>(path: string, type: __private.__types_globals__Constructor<T>, succeed?: (res: T[]) => void) {
        await this.updateBundle("bundle");

        let rs = null;
        let promise = new Promise<T[]>((resolve) => {
            rs = resolve;
        });

        let bundle = assetManager.getBundle("bundle");
        bundle && bundle.loadDir(path, type, (err, res) => {
            rs(res);
            if (err) {
                console.error('Failed to load bundle:', err);
                return;
            }
            succeed && succeed(res);
        });

        return promise;
    }

    static async loadBundleRes<T extends Asset>(path: string, type: __private.__types_globals__Constructor<T>, succeed?: (res: T) => void) {
        await this.updateBundle("bundle");

        let rs = null;
        let promise = new Promise<T[]>((resolve) => {
            rs = resolve;
        });

        let bundle = assetManager.getBundle("bundle");
        if (bundle) {
            bundle.load(path, type, (err, res) => {
                rs(res);
                if (err) {
                    console.error('Failed to load resource:', err);
                    return;
                }
                succeed(res);
            });
        } else {
            console.error('Bundle not found:', "bundle");
        }

        return promise;
    }

    static async updateBundle(bundleName: string, succeed?: () => void) {
        let _resolve = null;
        let ps = new Promise<void>((resolve, reject) => {
            _resolve = resolve;
        });
        if (assetManager.getBundle(bundleName) || bundleName.length == 0) {
            if (succeed) {
                succeed();
            }
            _resolve();
            return ps;
        }

        assetManager.loadBundle(bundleName, (err: Error, bundle: AssetManager.Bundle) => {
            if (err) {

                console.error('Failed to load bundle:', err);
            } else {
                if (succeed) {
                    succeed()
                }

                _resolve();
            }
        })
        return ps;
    }
}


